package com.nightpiter.view.drawer.advanced;

import static com.nightpiter.controller.log.Logger.logProfilerBegin;
import static com.nightpiter.controller.log.Logger.logProfilerEnd;

import java.util.ArrayList;
import java.util.Collection;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.PathEffect;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Style;

import com.nightpiter.model.MetroModel;
import com.nightpiter.model.objects.Hub;
import com.nightpiter.model.objects.HubComponent;
import com.nightpiter.model.objects.Station;
import com.nightpiter.model.objects.Transfer;
import com.nightpiter.model.objects.Tunnel;
import com.nightpiter.view.drawer.MetroDrawer;

/**
 * Advanced Implementation of MetroDrawer
 *  * 
 * @author Alexandr Melamud
 * @author Dmitriy Kozorez
 */

public class AdvancedMetroDrawer extends MetroDrawer {

	private float hubRadius = 9;

	private float stationRadius = 7;

	private Paint stationPaint = new Paint();

	private Paint tunnelPaint = new Paint();

	private Paint hubPaint = new Paint();

	private Paint hubHighlight = new Paint();

	private Collection<DrawingTunnel> drawingTunnels = new ArrayList<DrawingTunnel>();

	private Collection<DrawingTunnel> drawedTunnels = new ArrayList<DrawingTunnel>();

	Collection<HubComponent> componentsToUnite = new ArrayList<HubComponent>();

	private Collection<Hub> onTouchDrawed = new ArrayList<Hub>();

	TunnelResolver tr = new TunnelResolver();

	/**
	 * public constructor; initializes drawing paints
	 */
	public AdvancedMetroDrawer(MetroModel model) {
		super(model);
		HubResolver.extractHubComponents(model.getHubs());

		stationPaint.setAntiAlias(true);
		stationPaint.setColor(Color.WHITE);
		stationPaint.setStrokeCap(Paint.Cap.ROUND);

		tunnelPaint.setAntiAlias(true);
		tunnelPaint.setColor(Color.WHITE);
		tunnelPaint.setStrokeCap(Paint.Cap.ROUND);

		hubPaint.setAntiAlias(true);
		hubPaint.setColor(Color.BLACK);
		hubPaint.setStrokeCap(Paint.Cap.ROUND);

		hubHighlight.setAntiAlias(true);
		hubHighlight.setColor(Color.BLACK);
		hubHighlight.setStrokeCap(Paint.Cap.ROUND);
		hubHighlight.setColor(Color.argb(180, 255, 224, 0));

		this.initialization(model);

	}

	public DrawingTunnel toDrawTunnel(Tunnel tunnel) {
		DrawingTunnel newTunnel = new DrawingTunnel(tunnel);
		return newTunnel;
	}

	public void initialization(MetroModel model) {
		logProfilerBegin("preparing drawer");

		for (Tunnel tunnel : model.getTunnels()) {
			if (this.toDrawTunnel(tunnel) != null) {
				DrawingTunnel newTunnel = (DrawingTunnel) this
						.toDrawTunnel(tunnel);

				drawingTunnels.add((DrawingTunnel) newTunnel);
			}
		}

		for (DrawingTunnel dr : drawingTunnels) {
			if (TunnelResolver.backTunnel(dr.getTunnel()) != null) {
				DrawingTunnel temptunnel = this
						.searchDrawingTunnel(TunnelResolver.backTunnel(dr
								.getTunnel()));
				dr.setBack(temptunnel);
			} else {
				dr.setBack(null);
			}
		}

		for (DrawingTunnel tunnel : this.drawingTunnels) {
			if (tunnel.getBack() != null) {
				tunnel.setSinglesided(false);
			} else {
				tunnel.setSinglesided(true);
			}
		}
		// ///////////////////////////////////////////////////

		for (DrawingTunnel dr : this.drawingTunnels) {
			this.setTunnelCoord(dr, 0);
		}

		this.setParallelTunnelCoord(drawingTunnels);

		logProfilerEnd("preparing drawer");

		// this.model.setDrawingTunnels(drawingTunnels);

		// ///////////////////////////////////////////////////////////////////////////
	}

	/**
	 * Main drawer method which draws the full metro map
	 */
	public void drawMetro(Canvas canvas) {

		logProfilerBegin("Performing full metro draw");
		canvas.drawColor(Color.WHITE);

		this.drawedTunnels.clear();

		for (DrawingTunnel dr : this.drawingTunnels) {

			if (!this.drawedTunnels.contains(dr.getBack())) {

				this.simpleDrawTunnel(dr, canvas, false);
				this.drawedTunnels.add(dr);
			}
		}

		for (Station station : model.getStations()) {
			if (station.getTransfers().size() < 1) {
				this.drawStation(station, canvas);
			}
		}

		for (Hub hub : model.getHubs()) {
			this.drawHub(hub, canvas, !true);
		}
		logProfilerEnd("Drawing Metro completed");

	}

	// ///////////////////////////////////////////////////////////////////////////

	private void drawSector(float centerX, float centerY, float radius,
			float angleStart, float angleFinish, Canvas canvas, Paint paint) {

		paint.setStrokeWidth(radius);
		paint.setStrokeCap(Cap.BUTT);
		paint.setStyle(Style.FILL_AND_STROKE);
		RectF arcRect = new RectF(centerX - radius, centerY - radius, centerX
				+ radius, centerY + radius);

		float start = (float) ((angleStart / (Math.PI * 2)) * 360);
		float finish = (float) ((angleFinish / (Math.PI * 2)) * 360);

		canvas.drawArc(arcRect, start, finish - start, paint);
		arcRect = new RectF(centerX - radius / 2, centerY - radius / 2, centerX
				+ radius / 2, centerY + radius / 2);
		canvas.drawArc(arcRect, start, finish - start, paint);
		paint.setStyle(Style.FILL);
		paint.setStrokeCap(Cap.ROUND);

	}

	// /////////////drawing of hub//////////////////////////////////////

	private void drawHub(Hub hub, Canvas canvas, boolean isLighted) {

		// /////////////////drawing Background ///////////////////////////

		for (HubComponent component : hub.getComponents()) {
			float componentCenterX = realX(HubResolver
					.componentCoordinates(component).x);
			float componentCenterY = realY(HubResolver
					.componentCoordinates(component).y);

			hubPaint.setColor(Color.BLACK);
			canvas.drawCircle(componentCenterX, componentCenterY, hubRadius
					+ hubRadius / 2, hubPaint);
			for (HubComponent componentUnited : component.getComponentsUnited()) {

				hubPaint.setStrokeWidth(hubRadius + hubRadius / 3);
				canvas
						.drawLine(
								componentCenterX,
								componentCenterY,
								realX(HubResolver
										.componentCoordinates(componentUnited).x),
								realY(HubResolver
										.componentCoordinates(componentUnited).y),
								hubPaint);

			}
		}

		for (HubComponent component : hub.getComponents()) {
			float componentCenterX = realX(HubResolver
					.componentCoordinates(component).x);
			float componentCenterY = realY(HubResolver
					.componentCoordinates(component).y);
			hubPaint.setColor(Color.LTGRAY);
			canvas.drawCircle(componentCenterX, componentCenterY, hubRadius
					+ hubRadius / 2 - 1, hubPaint);
			for (HubComponent componentUnited : component.getComponentsUnited()) {
				hubPaint.setStrokeWidth(hubRadius + hubRadius / 3 - 2);
				canvas
						.drawLine(
								componentCenterX,
								componentCenterY,
								realX(HubResolver
										.componentCoordinates(componentUnited).x),
								realY(HubResolver
										.componentCoordinates(componentUnited).y),
								hubPaint);
			}
		}

		// ////////////// drawing transitions between HubComponents/////////

		for (HubComponent component : hub.getComponents()) {
			float componentCenterX = realX(HubResolver
					.componentCoordinates(component).x);
			float componentCenterY = realY(HubResolver
					.componentCoordinates(component).y);
			for (HubComponent componentUnited : component.getComponentsUnited()) {
				hubPaint.setColor(Color.BLACK);
				hubPaint.setStrokeWidth(hubRadius / 2 + 1);
				canvas
						.drawLine(
								componentCenterX,
								componentCenterY,
								realX(HubResolver
										.componentCoordinates(componentUnited).x),
								realY(HubResolver
										.componentCoordinates(componentUnited).y),
								hubPaint);
				hubPaint.setColor(Color.WHITE);
				hubPaint.setStrokeWidth(hubRadius / 2);
				canvas
						.drawLine(
								componentCenterX,
								componentCenterY,
								realX(HubResolver
										.componentCoordinates(componentUnited).x),
								realY(HubResolver
										.componentCoordinates(componentUnited).y),
								hubPaint);
				hubPaint.setStrokeWidth(1);
			}
		}

		// ///////////////// drawing HubComponents/////////////////////////

		for (HubComponent component : hub.getComponents()) {

			float componentCenterX = realX(HubResolver
					.componentCoordinates(component).x);
			float componentCenterY = realY(HubResolver
					.componentCoordinates(component).y);

			hubPaint.setColor(Color.BLACK);
			canvas.drawCircle(componentCenterX, componentCenterY, hubRadius,
					hubPaint);
			hubPaint.setColor(Color.WHITE);
			canvas.drawCircle(componentCenterX, componentCenterY,
					hubRadius - 1, hubPaint);

			float ang = 0;
			for (int j = 0; j < HubResolver.colorsInComponent(component).size(); j++) {
				hubPaint.setColor(HubResolver.colorsInComponent(component).get(
						j));

				this.drawSector(componentCenterX, componentCenterY, hubRadius
						- hubRadius / 3, ang, (float) (ang + (Math.PI * 2)
						/ HubResolver.colorsInComponent(component).size()),
						canvas, hubPaint);
				ang += (float) ((Math.PI * 2) / HubResolver.colorsInComponent(
						component).size());
			}
			hubPaint.setColor(Color.WHITE);
			hubPaint.setAlpha(130);
			canvas.drawCircle((int) componentCenterX + 1,
					(int) componentCenterY + 1, hubRadius / 2, hubPaint);
			hubPaint.setAlpha(160);
			canvas.drawCircle((int) componentCenterX + 1,
					(int) componentCenterY + 1, hubRadius / 4, hubPaint);

		}

	}

	// /////finish drawing of hubs///////////////////////////

	// /////drawing of Stations//////////////////////////////

	private void drawStation(Station station, Canvas canvas) {
		stationPaint.setColor(Color.BLACK);
		canvas.drawCircle(this.realX(station.getPosition().x), this
				.realY(station.getPosition().y), stationRadius, stationPaint);
		boolean tr = true;
		Tunnel t = (Tunnel) station.getTunnels().toArray()[0];
		int tempColor = t.getLine().getColor();
		for (int j = 0; j < station.getTunnels().size(); j++) {
			t = (Tunnel) station.getTunnels().toArray()[j];
			if (t.getLine().getColor() != tempColor) {
				tr = false;
			}
		}
		if (!tr) {
			tempColor = Color.WHITE;
		}
		stationPaint.setColor(tempColor);
		canvas.drawCircle(this.realX(station.getPosition().x), this
				.realY(station.getPosition().y), stationRadius - 1,
				stationPaint);
		if (tr) {
			stationPaint.setColor(Color.WHITE);
		} else {
			stationPaint.setColor(Color.LTGRAY);
		}

		stationPaint.setAlpha(130);
		canvas.drawCircle(this.realX(station.getPosition().x) + 1, this
				.realY(station.getPosition().y) + 1, 5 * stationRadius / 8,
				stationPaint);
		stationPaint.setAlpha(160);
		canvas.drawCircle(this.realX(station.getPosition().x) + 1, this
				.realY(station.getPosition().y) + 1, stationRadius / 3,
				stationPaint);

		stationPaint.setColor(Color.BLACK);
		stationPaint.setTextSize(stationRadius + 3);
		canvas.drawText(station.getName(), this.realX(station.getPosition().x)
				+ stationRadius + 1, this.realY(station.getPosition().y)
				+ stationRadius + 1, stationPaint);
	}

	// ////////setters for coordinates of drawingTunnels/////////////////

	private void setTunnelCoord(DrawingTunnel dr, float correction) {
		if (HubResolver.stationIsInHubs(dr.getTunnel().getFromStation()) == null) {
			if (HubResolver.stationIsInHubs(dr.getTunnel().getToStation()) == null) {

				Point from = dr.getTunnel().getFromStation().getPosition();
				Point to = dr.getTunnel().getToStation().getPosition();
				setSimpleTynnelCoord(dr, from.x, from.y, to.x, to.y, correction);

			} else {
				Point from = dr.getTunnel().getFromStation().getPosition();
				Point to = HubResolver.componentCoordinates(HubResolver
						.componentOfStation(dr.getTunnel().getToStation(),
								HubResolver.stationIsInHubs(dr.getTunnel()
										.getToStation())));
				setSimpleTynnelCoord(dr, from.x, from.y, to.x, to.y, correction);

			}
		} else {
			if (HubResolver.stationIsInHubs(dr.getTunnel().getToStation()) == null) {
				Point from = HubResolver.componentCoordinates(HubResolver
						.componentOfStation(dr.getTunnel().getFromStation(),
								HubResolver.stationIsInHubs(dr.getTunnel()
										.getFromStation())));
				Point to = dr.getTunnel().getToStation().getPosition();
				setSimpleTynnelCoord(dr, from.x, from.y, to.x, to.y, correction);

			} else {
				Point from = HubResolver.componentCoordinates(HubResolver
						.componentOfStation(dr.getTunnel().getFromStation(),
								HubResolver.stationIsInHubs(dr.getTunnel()
										.getFromStation())));
				Point to = HubResolver.componentCoordinates(HubResolver
						.componentOfStation(dr.getTunnel().getToStation(),
								HubResolver.stationIsInHubs(dr.getTunnel()
										.getToStation())));
				setSimpleTynnelCoord(dr, from.x, from.y, to.x, to.y, correction);
			}
		}
	}

	Collection<DrawingTunnel> setParallelTunnelCoord(
			Collection<DrawingTunnel> drawingTunnels) {
		Collection<DrawingTunnel> parallelTunnels = new ArrayList<DrawingTunnel>();


		for (DrawingTunnel tunnel : drawingTunnels) {

			int size = tr.formParallelTunnels(tunnel, drawingTunnels).size();
			
			
			if (tr.formParallelTunnels(tunnel, drawingTunnels).size() > 2) {
				Tunnel [] order = new Tunnel [size];
				int j=0;
				for (DrawingTunnel tun:tr.formParallelTunnels(tunnel,
						drawingTunnels)) {
					order[j] = tun.getTunnel();
					j+=1;
				}
				j=size-1;
				
				for (int k=j; k>=0; k--) {
					for (int m=0; m<=k-1; m++) {
						if (order[m].getLine().getColor()>order[m+1].getLine().getColor()) {
							Tunnel temp = order[m];
							order[m]=order[m+1];
							order[m+1] = temp;
						}
					}
				}				
				
				ArrayList <Tunnel> orderArray = new ArrayList<Tunnel>();
				
				for (int m=0; m<size; m++) {
					if (m==0){
						orderArray.add(order[m]);						
					}
					
					if (m>0) {
						if (!order[m].equals(order[m-1])) {
							orderArray.add(order[m]);
						}
					}					
				}
				
				Tunnel [] orderResorted = new Tunnel [orderArray.size()];
				
				int num = 0;
				for (Tunnel tun: orderArray) {
					orderResorted[num] = tun;
					num+=1;
				}

				float i = -this.stationRadius/2;
				if (tr.formParallelTunnels(tunnel, drawingTunnels).size() > 2) {
					for (DrawingTunnel tunnelPar : tr.formParallelTunnels(tunnel,
							drawingTunnels)) {
						if (!parallelTunnels.contains(tunnelPar)) {
							
							for (int k=0;k<orderArray.size();k++) {
								if ((tunnelPar == this.searchDrawingTunnel(orderResorted[k]))
										& (orderResorted[k]!=null)){
									this.setTunnelCoord (tunnelPar,i+ k*(3 * (stationRadius) / size));
									parallelTunnels.add(tunnelPar);
								}
							}
						}
					}
				}
			}
		}
			
		return parallelTunnels;
	}

	private void setSimpleTynnelCoord(DrawingTunnel dr, float fromX,
			float fromY, float toX, float toY, float correction) {

		double length = Math.sqrt((fromX-toX)*(fromX-toX)+(fromY-toY)*(fromY-toY));
		
		double sin=0;
		if (fromY>toY) {
			sin = (fromY-toY)/length;
		} else {
			sin = (toY-fromY)/length;
		}
		
		double cos=0;
		if (fromX>toX) {
			cos = (fromX-toX)/length;
		} else {
			cos = (toX-fromX)/length;
		}
		
		double angSin = Math.asin(sin);
		angSin = angSin + Math.PI/2;
		double angCos = Math.acos(cos);
		angCos = angCos + Math.PI/2;
		
		if (((fromX-toX)*(fromY-toY))>=0) {
			dr.fromX = fromX +  correction*((float)Math.cos(angCos)) / scale;
			dr.fromY = fromY + correction*((float)Math.sin(angSin)) / scale;
			dr.toX = toX + correction*((float)Math.cos(angCos)) / scale;
			dr.toY = toY + correction*((float)Math.sin(angSin)) / scale;
		} 
		if (((fromX-toX)*(fromY-toY))<0) {
			dr.fromX = fromX +  correction*((float)Math.cos(angCos)) / scale;
			dr.fromY = fromY - correction*((float)Math.sin(angSin)) / scale;
			dr.toX = toX + correction*((float)Math.cos(angCos)) / scale;
			dr.toY = toY - correction*((float)Math.sin(angSin)) / scale;
		}
		
		
	}

	// ///////////////////////////////////////////////////////////////////////
	// ==============drawing of tunnels using new methods===================//
	// ///////////////////////////////////////////////////////////////////////

	private void simpleDrawTunnel(DrawingTunnel dr, Canvas canvas,
			boolean isHighLighted) {

		if (isHighLighted) {
			tunnelPaint.setColor(Color.argb(180, 255, 224, 0));
			tunnelPaint.setStrokeWidth(3 * this.scale / 2);
			canvas.drawLine(realX(dr.fromX), realY(dr.fromY), realX(dr.toX),
					realY(dr.toY), tunnelPaint);
			tunnelPaint.setColor(Color.RED);
			tunnelPaint.setAlpha(100);
			tunnelPaint.setStrokeWidth(2 * this.scale);
			PathEffect effect = new PathDashPathEffect(makePathDashBig(),
					6 * scale / 5, scale / 5, PathDashPathEffect.Style.ROTATE);
			tunnelPaint.setPathEffect(effect);
			canvas.drawLine(realX(dr.fromX), realY(dr.fromY), realX(dr.toX),
					realY(dr.toY), tunnelPaint);
			tunnelPaint.setPathEffect(null);
		}
		tunnelPaint.setColor(Color.BLACK);
		tunnelPaint.setStrokeWidth(stationRadius);
		canvas.drawLine(realX(dr.fromX), realY(dr.fromY), realX(dr.toX),
				realY(dr.toY), tunnelPaint);

		tunnelPaint.setColor(dr.line.getColor());
		tunnelPaint.setStrokeWidth(stationRadius - 1);
		canvas.drawLine(realX(dr.fromX), realY(dr.fromY), realX(dr.toX),
				realY(dr.toY), tunnelPaint);

		tunnelPaint.setColor(Color.WHITE);
		tunnelPaint.setAlpha(170);
		tunnelPaint.setStrokeWidth(stationRadius / 2);
		canvas.drawLine(realX((dr.fromX)) + stationRadius / 7,
				realY((dr.fromY)) + stationRadius / 7, realX((dr.toX))
						+ stationRadius / 7, realY((dr.toY)) + stationRadius
						/ 7, tunnelPaint);

		// // drawing of one-side tunnels/////////////////////

		if (dr.isSinglesided()) {
			tunnelPaint.setColor(Color.WHITE);
			tunnelPaint.setAlpha(220);
			tunnelPaint.setStrokeWidth(stationRadius / 2);

			PathEffect effect = new PathDashPathEffect(makePathDash(),
					6 * scale / 5, scale / 5, PathDashPathEffect.Style.ROTATE);
			tunnelPaint.setPathEffect(effect);
			canvas.drawLine(realX(dr.fromX), realY(dr.fromY), realX(dr.toX),
					realY(dr.toY), tunnelPaint);

			tunnelPaint.setPathEffect(null);

			// }
			this.drawedTunnels.add(dr);
		}

	}

	private Path makePathDash() {
		Path p = new Path();

		float pos = 7 * this.scale / 24;
		p.moveTo(pos, 0);
		p.lineTo(0, -pos);
		p.lineTo(2 * pos, -pos);
		p.lineTo(3 * pos, 0);
		p.lineTo(2 * pos, pos);
		p.lineTo(0, pos);

		return p;
	}

	private Path makePathDashBig() {
		Path p = new Path();

		float pos = 7 * this.scale / 24;
		p.moveTo(pos, 0);
		p.lineTo(0, -3 * pos);
		p.lineTo(2 * pos, -3 * pos);
		p.lineTo(3 * pos, 0);
		p.lineTo(2 * pos, 3 * pos);
		p.lineTo(0, 3 * pos);

		return p;
	}

	// ///////////////////////////////////////////////////////////////////
	// ===================end of drawing================================//
	// ///////////////////////////////////////////////////////////////////

	private DrawingTunnel searchDrawingTunnel(Tunnel tunnel) {
		for (DrawingTunnel drawingTunnel : this.drawingTunnels) {
			if ((drawingTunnel.getTunnel().getToStation() == tunnel
					.getToStation())
					& (drawingTunnel.getTunnel().getFromStation() == tunnel
							.getFromStation())
					& (drawingTunnel.getTunnel().getLine() == tunnel.getLine())
					& (drawingTunnel.getTunnel().getTime() == tunnel.getTime())) {
				return drawingTunnel;
			}
		}
		return null;
	}

	public void setScale(float scale) {
		super.setScale(scale);
		stationRadius = scale - scale / 3;
		if (stationRadius < 1) {
			stationRadius = 1;
		}
		hubRadius = scale - scale / 8;
		if (hubRadius < 2) {
			hubRadius = 2;
		}
	}

	public void showWay(ArrayList<Tunnel> selectedTunnels,
			ArrayList<Transfer> selectedTransfers,
			ArrayList<Station> selectedStations, Canvas canvas) {
		ArrayList<Station> stationsToDraw = new ArrayList<Station>();
		ArrayList<Hub> hubsToDraw = new ArrayList<Hub>();
		ArrayList<HubComponent> componentsToDraw = new ArrayList<HubComponent>();

		for (Tunnel tunnel : selectedTunnels) {
			DrawingTunnel drawingTunnel = this.searchDrawingTunnel(tunnel);
			this.simpleDrawTunnel(drawingTunnel, canvas, true);
			stationsToDraw.add(tunnel.getToStation());
			if (!stationsToDraw.contains(tunnel.getFromStation())) {
				stationsToDraw.add(tunnel.getFromStation());
			}			
		}

		for (Transfer transfer : selectedTransfers) {
			for (HubComponent comp : transfer.getHub().getComponents()) {
				if (!componentsToDraw.contains(comp)) {
					for (Station stat : comp.getStations()) {
						if (stat == transfer.getFromStation()) {
							if (!componentsToDraw.contains(comp)) {
								componentsToDraw.add(comp);
							}
						}
						if (stat == transfer.getToStation()) {
							if (!componentsToDraw.contains(comp)) {
								componentsToDraw.add(comp);
							}
						}
					}
				}

			}

			if (!hubsToDraw.contains(transfer.getHub())) {
				hubsToDraw.add(transfer.getHub());
			}
		}
		
		for (Station station : stationsToDraw) {
			if (selectedStations.contains(station)) {
				this.selectStation(station, canvas, Color.argb(255, 255, 154,
						154));
			} else {
				this.selectStation(station, canvas);
			}
		}
		
		for (HubComponent component : componentsToDraw) {
			this.selectComponent(component, componentsToDraw, canvas, Color
					.argb(255, 255, 154, 154));
		}

		

	}

	public void selectStation(Station station, Canvas canvas) {
		this.selectStation(station, canvas, Color.argb(230, 255, 224, 0));
	}

	public void selectStation(Station station, Canvas canvas, int color) {
		if (station.getTransfers().isEmpty()) {

			stationPaint.setColor(color);
			canvas.drawCircle(this.realX(station.getPosition().x), this
					.realY(station.getPosition().y), stationRadius
					+ stationRadius / 2, stationPaint);
			this.drawStation(station, canvas);
		} else {
			for (Transfer transfer : station.getTransfers()) {
				Hub hub = transfer.getHub();
				if (hub != null) {
					if (!onTouchDrawed.contains(hub)) {
						for (HubComponent comp : hub.getComponents()) {
							for (Station stat : comp.getStations()) {
								if (stat == station) {
									this.selectComponent(comp,
											new ArrayList<HubComponent>(),
											canvas, color);
								}
							}
						}
						onTouchDrawed.add(hub);
					}
				}
			}
		}
		this.componentsToUnite.clear();
		onTouchDrawed.clear();
	}

	private void selectComponent(HubComponent component,
			Collection<HubComponent> componentsToDraw, Canvas canvas, int color) {
		float componentCenterX = realX(HubResolver
				.componentCoordinates(component).x);
		float componentCenterY = realY(HubResolver
				.componentCoordinates(component).y);

		hubHighlight.setColor(color);

		for (HubComponent comp : component.getComponentsUnited()) {
			if (componentsToDraw.contains(comp)) {
				if (!this.componentsToUnite.contains(comp)) {
					hubPaint.setStrokeWidth(7 * hubRadius / 3);
					hubPaint.setColor(hubHighlight.getColor());
					canvas.drawLine(componentCenterX, componentCenterY,
							realX(HubResolver.componentCoordinates(comp).x),
							realY(HubResolver.componentCoordinates(comp).y),
							hubPaint);

					hubPaint.setColor(Color.BLACK);
					hubPaint.setStrokeWidth(hubRadius + hubRadius / 3);
					canvas.drawLine(componentCenterX, componentCenterY,
							realX(HubResolver.componentCoordinates(comp).x),
							realY(HubResolver.componentCoordinates(comp).y),
							hubPaint);

					hubPaint.setColor(Color.LTGRAY);

					hubPaint.setStrokeWidth(hubRadius + hubRadius / 3 - 2);
					canvas.drawLine(componentCenterX, componentCenterY,
							realX(HubResolver.componentCoordinates(comp).x),
							realY(HubResolver.componentCoordinates(comp).y),
							hubPaint);

					hubPaint.setColor(Color.BLACK);
					hubPaint.setStrokeWidth(hubRadius / 2 + 1);
					canvas.drawLine(componentCenterX, componentCenterY,
							realX(HubResolver.componentCoordinates(comp).x),
							realY(HubResolver.componentCoordinates(comp).y),
							hubPaint);
					hubPaint.setColor(Color.WHITE);
					hubPaint.setStrokeWidth(hubRadius / 2);
					canvas.drawLine(componentCenterX, componentCenterY,
							realX(HubResolver.componentCoordinates(comp).x),
							realY(HubResolver.componentCoordinates(comp).y),
							hubPaint);
					hubPaint.setStrokeWidth(1);

					if (!this.componentsToUnite.contains(component)) {
						this.componentsToUnite.add(component);
					}
				}

			}

		}

		hubHighlight.setStrokeWidth(3 * this.hubRadius / 5);
		hubHighlight.setStrokeCap(Cap.BUTT);
		hubHighlight.setStyle(Style.STROKE);
		RectF arcRect = new RectF(componentCenterX - 10 * this.hubRadius / 6,
				componentCenterY - 10 * this.hubRadius / 6, componentCenterX
						+ 10 * this.hubRadius / 6, componentCenterY + 10
						* this.hubRadius / 6);

		canvas.drawArc(arcRect, 0, 360, hubHighlight);

		hubHighlight.setStyle(Style.FILL);
		hubHighlight.setStrokeCap(Cap.ROUND);
		
		hubPaint.setColor(Color.BLACK);
		canvas.drawCircle(componentCenterX, componentCenterY, hubRadius
				+ hubRadius / 2, hubPaint);

		hubPaint.setColor(Color.LTGRAY);
		canvas.drawCircle(componentCenterX, componentCenterY, hubRadius
				+ hubRadius / 2 - 1, hubPaint);

		hubPaint.setColor(Color.BLACK);
		canvas.drawCircle(componentCenterX, componentCenterY, hubRadius,
				hubPaint);
		hubPaint.setColor(Color.WHITE);
		canvas.drawCircle(componentCenterX, componentCenterY, hubRadius - 1,
				hubPaint);

		float ang = 0;
		for (int j = 0; j < HubResolver.colorsInComponent(component).size(); j++) {
			hubPaint.setColor(HubResolver.colorsInComponent(component).get(j));

			this.drawSector(componentCenterX, componentCenterY, hubRadius
					- hubRadius / 3, ang, (float) (ang + (Math.PI * 2)
					/ HubResolver.colorsInComponent(component).size()), canvas,
					hubPaint);
			ang += (float) ((Math.PI * 2) / HubResolver.colorsInComponent(
					component).size());
		}
		hubPaint.setColor(Color.WHITE);
		hubPaint.setAlpha(130);
		canvas.drawCircle((int) componentCenterX + 1,
				(int) componentCenterY + 1, hubRadius / 2, hubPaint);
		hubPaint.setAlpha(160);
		canvas.drawCircle((int) componentCenterX + 1,
				(int) componentCenterY + 1, hubRadius / 4, hubPaint);

	}

}
